//
// Created by 沈昊 on 2022/2/22.
//

#ifndef ZLMEDIAKIT_VARYFRAMEWRITER_H
#define ZLMEDIAKIT_VARYFRAMEWRITER_H

#include <Extension/Frame.h>
#include <memory>
#include <FFmpeg/FFmpegEncoder.hpp>
#include <FFmpeg/FFmpegDecoder.hpp>
#include <FFmpeg/CoderVideoTransfer.hpp>
#include <FFmpeg/impl/FFmpegEncoder.hpp>

class DefaultFrameWriter: public mediakit::FrameWriterInterface{
public:
    using Ptr = std::shared_ptr<DefaultFrameWriter>;
public:
    bool inputFrame(const mediakit::Frame::Ptr &frame) override{
        if(on_frame){
            on_frame(frame);
        }
        return true;
    }
    void setOnFrame(std::function<void(const mediakit::Frame::Ptr &frame)> f){
        on_frame = f;
    }
private:
    std::function<void(const mediakit::Frame::Ptr &frame)> on_frame;
};

class VaryFrameWriter: public mediakit::FrameWriterInterface{
public:
    using Ptr = std::shared_ptr<VaryFrameWriter>;
public:
    VaryFrameWriter(size_t width, size_t height, const AVCodecID&);
    bool inputFrame(const mediakit::Frame::Ptr &frame) override;
    void setOnVaryFrame(std::function<void(const CoderContext&, FFmpeg::Frame::Ptr)>&& );
private:
    void initiallze(const mediakit::CodecId& id);
private:
    std::shared_ptr<FFmpegDecoder> decoder;
    std::shared_ptr<FFmpegEncoder<CoderTransfer<Video>>> encoder;
    std::once_flag flag;
    std::function<void(const CoderContext& context, FFmpeg::Frame::Ptr)> func;
    size_t width;
    size_t height;
    AVCodecID id;
};

class VaryFrameWriterDispatcher : public mediakit::FrameWriterInterface{
public:
    bool inputFrame(const mediakit::Frame::Ptr &frame) override{
        if(on_frame){
            on_frame(frame);
            return true;
        }
        return false;
    }
    void setOnVaryDispatcherFrame(const std::function<void(const mediakit::Frame::Ptr&)>& p){
        if(p) on_frame = p;
    }
private:
    std::function<void(const mediakit::Frame::Ptr&)> on_frame;
};



#endif // ZLMEDIAKIT_VARYFRAMEWRITER_H
